package com.lyhlmj.oop_client.Frames.PlayFrame.Panels;

import com.lyhlmj.oop_client.ClientOperation.ClientUtil.Client;
import com.lyhlmj.oop_client.Threads.GetPlayStatusTask;
import com.lyhlmj.oop_client.Utils.ChessUtils;
import com.lyhlmj.oop_client.Utils.GetScreenSize;
import com.lyhlmj.oop_client.Utils.PenUtil;
import com.lyhlmj.oop_client.Utils.Request;
import org.json.JSONObject;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

// 点击ReadyButton且匹配成功后再显示棋盘，显示棋盘后才启动GetPlayStatus线程
public class ChessBoardPanel extends JPanel {
    //  设置ChessBoard背景
    private Image ChessBoardImage;

    private Window owner;
    private Client client = Client.client;

    //  得到Frame的大小
    int width = GetScreenSize.getFitSize()[0];
    int height = GetScreenSize.getFitSize()[1];
    //  得到棋盘大小
    private int ChessBoardLength = (int) (width * 0.5);
    //  得到棋盘行列间距
    private int lineSpace = ChessBoardLength / 16;
    //  定义行，列
    private int row, column;
    //  定义棋盘的左边距和上边距
    private int marginLeft = (int) (0.05 * height);
    private int marginTop = (int) (0.005 * height);

    //  保存所有棋子 0:无棋子 1:黑子 2:白子
    private int[][] allChess = new int[15][15];

    //  棋谱结果字符串（传给后端保存）
    private String chessResult;
    //  判断当前轮到自己还是对手
    private static String turn;  //对turn进行上锁，要求互斥访问
    //  判断玩家执黑执白，后端传入
    private int color;
    //  判断赢家
    private String winner;

    //棋盘Panel
    public ChessBoardPanel(Window owner) {
        this.owner = owner;

        this.setOpaque(false);//    设置背景透明
        try {
            this.ChessBoardImage = ImageIO.read(new File("data/oop棋盘背景.jpg"));
            this.repaint();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //  开始游戏前的初始化
        initialChessBoard();
        //建立棋盘绘制线程
        Painting paint = new Painting();
        paint.start();
    }

    @Override
    protected synchronized void paintComponent(Graphics g) {
        super.paintComponent(g);
//        创建双缓冲画笔
        BufferedImage bufferedImage = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D bufferPen = bufferedImage.createGraphics();

//          读取图片文件
        if (ChessBoardImage != null) {
            g.drawImage(ChessBoardImage, marginLeft, marginTop, ChessBoardLength, ChessBoardLength, null);
        }

        //  绘棋盘
        paintBoard(bufferPen);
        //  绘制棋子
        savedAllChess(bufferPen);

        //  定义画笔
        Graphics2D pen = PenUtil.setPen(g);

        pen.drawImage(bufferedImage, 0, 0, this);
    }

    //  绘制已经下过的全部棋子
    public void savedAllChess(Graphics2D pen) {
        //  allChess[0]~[14]
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                if (allChess[i][j] == 1) {   //  绘制黑子
                    int tempX = marginLeft + (i + 1) * lineSpace - lineSpace / 2;
                    int tempY = marginTop + (j + 1) * lineSpace - lineSpace / 2;
                    pen.fillOval(tempX, tempY, lineSpace, lineSpace);
                }
                if (allChess[i][j] == 2) {   //  绘制白子
                    int tempX = marginLeft + (i + 1) * lineSpace - lineSpace / 2;
                    int tempY = marginTop + (j + 1) * lineSpace - lineSpace / 2;
                    pen.setColor(Color.WHITE);
                    pen.fillOval(tempX, tempY, lineSpace, lineSpace);
                    pen.setColor(Color.BLACK);
                    pen.drawOval(tempX, tempY, lineSpace, lineSpace);
                }
            }
        }
    }

    private void setMouseListener(Painting painting) {
        this.addMouseListener(new MouseAdapter() {
            @Override
            public synchronized void mousePressed(MouseEvent e) {
                synchronized (turn) {  //对turn进行互斥访问，避免用户恶意连续点击
                    if (turn.equals(client.getUsername())) {  //判断当前回合是否为当前用户
                        //  棋子坐标
                        int x = e.getX();
                        int y = e.getY();
                        //  xx和yy是距离最近的点的坐标
                        int xx = 0;
                        int yy = 0;
                        if ((x > marginLeft + lineSpace) && (x < marginLeft + 16 * lineSpace) && (y > marginTop + lineSpace) && (x < marginTop + 16 * lineSpace)) {
                            if ((x - marginLeft) % lineSpace < lineSpace / 2) {
                                xx = (x - marginLeft) / lineSpace - 1;
//                            System.out.println("距离最近的坐标xx:"+ ( xx+1 ) );
                            } else {
                                xx = (x - marginLeft) / lineSpace;
//                            System.out.println("距离最近的坐标xx:"+ ( xx+1 ) );
                            }
                            if ((y - marginTop) % lineSpace < lineSpace / 2) {
                                yy = (y - marginTop) / lineSpace - 1;
//                            System.out.println("距离最近的坐标yy:" + ( yy+1 ) );
                            } else {
                                yy = (y - marginTop) / lineSpace;
//                            System.out.println("距离最近的坐标yy:" + ( yy+1 ) );
                            }
                        }

                        //  如果当前落子位置还没有棋子，则落子成功
                        if (allChess[xx][yy] == 0) {
                            allChess[xx][yy] = color;
                            //  落子后立即重新绘制
                            repaint();

                            //  打印棋谱矩阵
//                        int countNum = 0;   //  计数换行
//                        for (int i = 0; i < 15; i++) {
//                            for (int j = 0; j < 15; j++) {
//                                System.out.print(" " + allChess[i][j]);
//                                countNum++;
//                                if (countNum % 15 == 0) {
//                                    System.out.println(" ");
//                                }
                            //在结果字符串中修改xx yy对应的字符值
                            int index = xx * 15 + yy;
                            String changeChar = "" + allChess[xx][yy];
                            //        将resultString字符串的index索引位置的字符替换为changeChar
                            chessResult = chessResult.substring(0, index) + changeChar + chessResult.substring(index + 1);

                            //添加请求发送（告知后端当前用户下棋）
                            //落子
                            turn = getNextTurn(client.getUsername());  //将当前回合置为对方回合，自身不可下棋
                            JSONObject jsonReq = Request.getJsonObject("doPlay",
                                    "chessResult", chessResult,
                                    "username", client.getUsername(),
                                    "turn", turn,
                                    "playId", Client.client.getPlayId().toString()
                            );
                            try {  //向后端发送落子请求
                                client.send(jsonReq);
                            } catch (Exception exception) {
                                exception.printStackTrace();
                            }
//                            }
//                        }
                            //  返回棋谱结果字符串
//                        System.out.println("返回棋谱结果字符串：");
//                        System.out.println(chessResult);

                            //判断游戏是否结束，有一方获胜
                            boolean isWin = ChessUtils.checkWin(allChess, xx, yy);

                            if (isWin) {
                                //  输出游戏结果
                                if (allChess[xx][yy] == 1) System.out.println("黑方获胜，游戏结束！");
                                else if (allChess[xx][yy] == 2) System.out.println("白方获胜，游戏结束！");

                                //如果有人完成下棋，向后端发出获胜请求，对对局结果进行保存处理。
                                jsonReq = Request.getJsonObject("win", "username", client.getUsername(), "chatRoomId", client.getChatRoomId());
                                try {
                                    synchronized (Client.client){
                                        client.send(jsonReq);
                                    }
                                } catch (Exception exception) {
                                }

                                //有用户获胜后，终止绘制线程
                                try {
                                    Thread.sleep(300);
                                } catch (InterruptedException interruptedException) {
                                }
                                painting.doStop();
                            }
                        }
                    } else {
                        System.out.println("当前不是您的回合！");
                    }
                }
            }
        });
    }

    //该线程用来每间隔0.5s进行一次棋盘的重新绘制
    public class Painting extends Thread {
        boolean quitFlag = false;  //终止标识符，为true时循环终止

        public Painting() {
            //  设置鼠标点击监听器
            setMouseListener(this);
        }

        //用来终止当前进程
        public void doStop() {
            quitFlag = true;
            this.interrupt(); // 让  sleep() 立即中止
            try {
                this.join(); // 等待本线程结束后再退出
            } catch (Exception e) {
            }
        }

        @Override
        public void run() {
            while (!quitFlag) {
                try {
                    sleep(200);  //每0.2s执行一次
                } catch (InterruptedException e) {
                }

                GetPlayStatusTask getPlayStatusTask = client.getPlayStatusTask;
                if (getPlayStatusTask != null && getPlayStatusTask.getTurn() != null && !getPlayStatusTask.getTurn().equals("")) {  //更新对局信息
                    color = Integer.valueOf(getPlayStatusTask.getColor());
                    turn = getPlayStatusTask.getTurn();
//                    System.out.println(turn);
                    chessResult = getPlayStatusTask.getChessResult();
                    //将chessResult字符串转化为allChess数组
                    for (int i = 0; i < 15; i++) {
                        for (int j = 0; j < 15; j++) {
                            allChess[i][j] = charToInt(chessResult.charAt(i * 15 + j));
                        }
                    }
                }
                //  绘制棋盘
                repaint();
            }
        }
    }

    //当前用户下完棋，返回下一个下棋的用户
    private String getNextTurn(String username) {
        String[] players = client.getPlayers();
        if (username.equals(players[0])) {
            return players[1];
        } else {
            return players[0];
        }
    }

    private int charToInt(int charInt) {
        if (charInt == 48) {
            return 0;
        } else if (charInt == 49) {
            return 1;
        } else {
            return 2;
        }
    }

    //绘制棋盘的方法
    private void paintBoard(Graphics2D pen) {
        Paint color = Color.black;
        pen.setPaint(color);
        pen.setStroke(new BasicStroke(4.0f));
        //  棋盘横行
        //  (int)(0.05 * height)是棋盘横向的边距
        //  (int)(0.01 * height)是棋盘竖向的边距
        for (row = 1; row <= 15; row++) {
            pen.drawLine(marginLeft + lineSpace,
                    marginTop + row * lineSpace,
                    (marginLeft + 15 * lineSpace),
                    marginTop + row * lineSpace);
        }
        //  棋盘竖列
        for (column = 1; column <= 15; column++) {
            pen.drawLine(marginLeft + column * lineSpace,
                    marginTop + lineSpace,
                    (marginLeft + column * lineSpace),
                    marginTop + 15 * lineSpace);
        }

        //  绘制棋盘点位
        pen.fillOval(marginLeft + 4 * lineSpace, marginTop + 4 * lineSpace, 6, 6);
        pen.fillOval(marginLeft + 12 * lineSpace, marginTop + 4 * lineSpace, 6, 6);
        pen.fillOval(marginLeft + 4 * lineSpace, marginTop + 12 * lineSpace, 6, 6);
        pen.fillOval(marginLeft + 12 * lineSpace, marginTop + 12 * lineSpace, 6, 6);
        pen.fillOval(marginLeft + 8 * lineSpace, marginTop + 8 * lineSpace, 6, 6);
    }

    //  初始化空棋谱结果字符串
    public void initialChessBoard() {
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                String resultChar = "0";
                chessResult += resultChar;
            }
        }
    }
}
